// <copyright file="AutoComplete.cs" company="YUIAsp.Net">
// Copyright (c) 2009 All Right Reserved
// </copyright>
// <author>raul popescu</author>
// <email>dev@yuiasp.net</email>
// <date>2009-01-30</date>
// <summary>YUIAsp.Net File</summary>

using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using YUIAspNet.Common;

#region Embedded resources definitions
[assembly: WebResource("YUIAspNet.AutoComplete.AutoComplete.js", "text/javascript")]
[assembly: WebResource("YUIAspNet.EmbeddedSkins.DefaultSkin.AutoComplete.autocomplete-skin.css", "text/css", PerformSubstitution = true)]
[assembly: WebResource("YUIAspNet.EmbeddedSkins.DefaultSkin.loading.gif", "image/gif")]

#endregion

namespace YUIAspNet
{
    /// <summary>
    /// AutoComplete control based on YUI AutoComplete widget.
    /// </summary>
    [ToolboxItem(true)]
    [ParseChildren(true)]
    public class AutoComplete : YUIScriptBaseControl, INamingContainer
    {
        Panel _autocompleteContainer;
        TextBox _input;
        Panel _resultContainer;
        Image _loadingImage;

        /// <summary>
        /// Initializes a new instance of the <see cref="AutoComplete"/> class.
        /// </summary>
        public AutoComplete()
        {
            this.Init += new EventHandler(AutoComplete_Init);
            this.PreRender += new EventHandler(AutoComplete_PreRender);

            _autocompleteContainer = new Panel();
            _autocompleteContainer.ID = "autocompleteContainer";

            _input = new TextBox();
            _input.ID = "input";

            _resultContainer = new Panel();
            _resultContainer.ID = "results";
            _loadingImage = new Image();
            _loadingImage.ID = "loading";
            
            // defaults
            this.MaxResultsDisplayed = 10;
            this.MinQueryLength = 1;
            this.QueryDelay = 0.2F;
        }

        void AutoComplete_Init(object sender, EventArgs e)
        {
            this.Controls.Add(_autocompleteContainer);

            this._autocompleteContainer.Controls.Add(_input);
            this._autocompleteContainer.Controls.Add(_resultContainer);
            this._autocompleteContainer.Controls.Add(_loadingImage);

            this._autocompleteContainer.CssClass += " yui-ac";
        }

        void AutoComplete_PreRender(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(_loadingImage.ImageUrl))
                _loadingImage.ImageUrl = FindSkinImage(null, "loading.gif");

            _loadingImage.Style.Add("display", "none");
            _loadingImage.Style.Add("position", "absolute");
            _loadingImage.Style.Add("right", "0px");
            _loadingImage.Style.Add("top", "2px");

            if (string.IsNullOrEmpty(AutoCompleteCode))
                AutoCompleteCode = this.ID;
        }

        

        /// <summary>
        /// Registers the style sheets for the current control.
        /// Must be overriden in the parent control to add any css file reference.
        /// </summary>
        protected override void RegisterStyleSheets()
        {
            this.RegisterEmbeddedStylesheet("AutoComplete", "autocomplete-skin.css");
        }

        /// <summary>
        /// Register the values to send to the client control for initialization.
        /// </summary>
        protected override void RegisterClientInitialization()
        {
            AddProperty("TextControl", _input.ClientID);
            AddProperty("ResultContainer", _resultContainer.ClientID);
            AddProperty("LoadingImage", _loadingImage.ClientID);

            AddProperty("AllowBrowserAutocomplete", AllowBrowserAutocomplete);
            AddProperty("AlwaysShowContainer", AlwaysShowContainer);
            AddProperty("TypeAhead", TypeAhead);
            AddProperty("TypeAheadDelay", TypeAheadDelay);
            AddProperty("AnimateHorizontally", AnimateHorizontally);
            AddProperty("AnimateVertically", AnimateVertically);
            AddProperty("AnimationSpeed", AnimationSpeed);
            AddProperty("AutoHighlight", AutoHighlight);
            AddProperty("ForceSelection", ForceSelection);
            AddProperty("HighlightCssClass", HighlightCssClass);
            AddProperty("PreHighlightCssClass", PreHighlightCssClass);
            AddProperty("MaxResultsDisplayed", MaxResultsDisplayed);
            AddProperty("MinQueryLength", MinQueryLength);
            AddProperty("QueryDelay", QueryDelay);
            AddProperty("AutoCompleteCode", AutoCompleteCode);

            AddProperty("SupressInputUpdate", SupressInputUpdate);
            AddProperty("UseIFrame", UseIFrame);
            AddProperty("UseShadow", UseShadow);

            if (this.Source != null)
                AddProperty("Source", Source.Serialize(), true);
            else
                throw new RequiredPropertyException("Source");

            if (!string.IsNullOrEmpty(OnClientDataRequested))
                AddEvent("OnDataRequested", OnClientDataRequested);
            if (!string.IsNullOrEmpty(OnClientDataRecieved))
                AddEvent("OnDataRecieved", OnClientDataRecieved);
            if (!string.IsNullOrEmpty(OnClientDataError))
                AddEvent("OnDataError", OnClientDataError);
            if (!string.IsNullOrEmpty(OnClientContainerExpand))
                AddEvent("OnContainerExpand", OnClientContainerExpand);
            if (!string.IsNullOrEmpty(OnClientContainerCollapse))
                AddEvent("OnContainerCollapse", OnClientContainerCollapse);
            if (!string.IsNullOrEmpty(OnClientItemSelected))
                AddEvent("OnItemSelected", OnClientItemSelected);
            if (!string.IsNullOrEmpty(OnClientTextboxLeave))
                AddEvent("OnTextboxLeave", OnClientTextboxLeave);
            if (!string.IsNullOrEmpty(OnClientTextboxFocus))
                AddEvent("OnTextboxFocus", OnClientTextboxFocus);
            if (!string.IsNullOrEmpty(OnClientTextboxKeyPressed))
                AddEvent("OnTextboxKeyPressed", OnClientTextboxKeyPressed);
            if (!string.IsNullOrEmpty(OnClientCustomFormat))
                AddEvent("OnCustomFormat", OnClientCustomFormat);
        }

        /// <summary>
        /// Registers any additional scripts to include for this control.
        /// </summary>
        protected override void RegisterScriptReferences()
        {
            AddScriptReference(new ScriptReference("YUIAspNet.AutoComplete.AutoComplete.js", this.GetType().Assembly.FullName));
        }

        #region Public properties
        /// <summary>
        /// Gets or sets the width of the Web server control.
        /// </summary>
        /// <value></value>
        /// <returns>A <see cref="T:System.Web.UI.WebControls.Unit"/> that represents the width of the control. The default is <see cref="F:System.Web.UI.WebControls.Unit.Empty"/>.</returns>
        /// <exception cref="T:System.ArgumentException">The width of the Web server control was set to a negative value. </exception>
        public override Unit Width
        {
            get { return base.Width; }
            set
            {
                base.Width = value;
                this._autocompleteContainer.Width = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether to allow browser autocomplete.
        /// </summary>
        /// <value>
        /// 	<c>true</c> to allow browser autocomplete; otherwise, <c>false</c>.
        /// </value>
        public bool AllowBrowserAutocomplete { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to always show the results container.
        /// </summary>
        /// <value><c>true</c> to always show container; otherwise, <c>false</c>.</value>
        public bool AlwaysShowContainer { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether type ahead is enabled.
        /// By enableing type ahead, the textbox where the user types the query will be pre-populated with the first result in the result list.
        /// </summary>
        /// <value><c>true</c> to enable type ahead; otherwise, <c>false</c>.</value>
        public bool TypeAhead { get; set; }

        /// <summary>
        /// Gets or sets the type ahead delay.
        /// </summary>
        /// <value>The type ahead delay.</value>
        public float TypeAheadDelay { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to animate the display of the results container horizontally.
        /// </summary>
        /// <value><c>true</c> to animate horizontally; otherwise, <c>false</c>.</value>
        public bool AnimateHorizontally { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to animate the display of the results container vertically.
        /// </summary>
        /// <value><c>true</c> to animate vertically; otherwise, <c>false</c>.</value>
        public bool AnimateVertically { get; set; }

        /// <summary>
        /// Gets or sets the animation speed.
        /// </summary>
        /// <value>The animation speed.</value>
        public float AnimationSpeed { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to auto highlight the first item in the result list.
        /// </summary>
        /// <value><c>true</c> to enable auto highlight; otherwise, <c>false</c>.</value>
        public bool AutoHighlight { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to force the selection of an item.
        /// </summary>
        /// <value><c>true</c> to force selection; otherwise, <c>false</c>.</value>
        public bool ForceSelection { get; set; }

        /// <summary>
        /// Gets or sets the highlight CSS class.
        /// </summary>
        /// <value>The highlight CSS class.</value>
        public string HighlightCssClass { get; set; }

        /// <summary>
        /// Gets or sets the pre highlight CSS class.
        /// </summary>
        /// <value>The pre highlight CSS class.</value>
        public string PreHighlightCssClass { get; set; }

        /// <summary>
        /// Gets or sets the maximum number of results displayed.
        /// </summary>
        /// <value>The max results displayed.</value>
        public int MaxResultsDisplayed { get; set; }

        /// <summary>
        /// Gets or sets the minimum length of the query for which a request is made to the server.
        /// </summary>
        /// <value>The length of the min query.</value>
        public int MinQueryLength { get; set; }

        /// <summary>
        /// Gets or sets the query delay.
        /// </summary>
        /// <value>The query delay.</value>
        public float QueryDelay { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to supress input update.
        /// </summary>
        /// <value><c>true</c> to supress input update; otherwise, <c>false</c>.</value>
        public bool SupressInputUpdate { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to use iframe.
        /// </summary>
        /// <value><c>true</c> to use iframe; otherwise, <c>false</c>.</value>
        public bool UseIFrame { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to display a shadow for the container.
        /// </summary>
        /// <value><c>true</c> to use shadow; otherwise, <c>false</c>.</value>
        public bool UseShadow { get; set; }

        /// <summary>
        /// Gets or sets the auto complete code.
        /// Having multiple instances of the control on the page and same handler for all AutoComplete controls, this property allows you to differentiate between them.
        /// </summary>
        /// <value>The auto complete code.</value>
        public string AutoCompleteCode { get; set; }

        /// <summary>
        /// Gets or sets the source.
        /// </summary>
        /// <value>The source.</value>
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public DataSourceBase Source { get; set; }

        /// <summary>
        /// Gets or sets the on client data requested.
        /// </summary>
        /// <value>The on client data requested.</value>
        public string OnClientDataRequested { get; set; }

        /// <summary>
        /// Gets or sets the on client data recieved.
        /// </summary>
        /// <value>The on client data recieved.</value>
        public string OnClientDataRecieved { get; set; }

        /// <summary>
        /// Gets or sets the on client data error.
        /// </summary>
        /// <value>The on client data error.</value>
        public string OnClientDataError { get; set; }

        /// <summary>
        /// Gets or sets the on client container expand.
        /// </summary>
        /// <value>The on client container expand.</value>
        public string OnClientContainerExpand { get; set; }

        /// <summary>
        /// Gets or sets the on client container collapse.
        /// </summary>
        /// <value>The on client container collapse.</value>
        public string OnClientContainerCollapse { get; set; }

        /// <summary>
        /// Gets or sets the on client item selected.
        /// </summary>
        /// <value>The on client item selected.</value>
        public string OnClientItemSelected { get; set; }

        /// <summary>
        /// Gets or sets the on client textbox leave.
        /// </summary>
        /// <value>The on client textbox leave.</value>
        public string OnClientTextboxLeave { get; set; }

        /// <summary>
        /// Gets or sets the on client textbox focus.
        /// </summary>
        /// <value>The on client textbox focus.</value>
        public string OnClientTextboxFocus { get; set; }

        /// <summary>
        /// Gets or sets the on client textbox key pressed.
        /// </summary>
        /// <value>The on client textbox key pressed.</value>
        public string OnClientTextboxKeyPressed { get; set; }

        /// <summary>
        /// Gets or sets the on client custom format.
        /// </summary>
        /// <value>The on client custom format.</value>
        public string OnClientCustomFormat { get; set; } 
        #endregion
    }
}
